using System;
using System.Collections.Generic;
using System.IO;

namespace Gloom
{
	public class TranslatedManagedGLFunc
	{
		public string Name;
		public string ReturnType;
		public string[] Parameters;
		
		public string ReturnConversionPattern;
		public string ReturnConversionPrefix;
		public string ReturnConversionPostfix;
		public string[] ParametersConversionPattern;
		public string[] ParametersConversionPrefixes;
		public string[] ParametersConversionPostfixes;
		
		public bool MustDoLateReturn;
		
		private TranslatedManagedGLFunc() { }
		
		public static bool TryTranslate(UntranslatedGLFunc u, TranslatedUnmanagedGLFunc tugf, out TranslatedManagedGLFunc tmgf, StreamWriter infoLog, StreamWriter failLog)
		{
			infoLog.WriteLine("TranslatedManagedGLFunc.TryTranslate: Translation begins.");
			
			tmgf = new TranslatedManagedGLFunc();
			tmgf.Name = u.Name;
			tmgf.Parameters = new string[u.ParamsNameType.Count];
			tmgf.ParametersConversionPattern = new string[u.ParamsNameType.Count];
			tmgf.ParametersConversionPostfixes = new string[u.ParamsNameType.Count];
			tmgf.ParametersConversionPrefixes = new string[u.ParamsNameType.Count];
			tmgf.MustDoLateReturn = false;
			
			int i = 0;
			foreach (KeyValuePair<string, string> kvp in u.ParamsNameType)
			{
				// Translate type!
				string utype = tugf.Parameters[i].Substring(0, tugf.Parameters[i].LastIndexOf(' '));
				string newType;
				string[] oldTypeBits = kvp.Value.Split(' ');
				bool b = ManagedGLTypeTranslator.TryTranslate(oldTypeBits[0], oldTypeBits[1], oldTypeBits[2], out newType, infoLog, failLog);
				
				if (!b)
					return false;
				
				tmgf.Parameters[i] = newType + " " + GLTypePrimitiveMapper.MakeArgNameSafe(kvp.Key);
				bool late;
				tmgf.ParametersConversionPattern[i] = ManagedUnmanagedTypeTranslator.GetArgTranslatePattern(
						newType, utype, out tmgf.ParametersConversionPrefixes[i], out tmgf.ParametersConversionPostfixes[i], out late);
				if (late)
					tmgf.MustDoLateReturn = true;
				i++;
			}
			
			bool br = ManagedGLTypeTranslator.TryTranslate(u.ReturnType, "in", "value", out tmgf.ReturnType, infoLog, failLog);
			if (!br)
				return false;
			
			tmgf.ReturnConversionPattern = ManagedUnmanagedTypeTranslator.GetRetTranslatePattern(tmgf.ReturnType, tugf.ReturnType,
					out tmgf.ReturnConversionPrefix, out tmgf.ReturnConversionPostfix);
			
			return true;
		}
		

		
		public override string ToString()
		{
			string s = "\t\tpublic static unsafe " + ReturnType + " " + GLFuncNameMunger.GetManagedGLFuncName(Name) + "(";
			
			foreach (string param in Parameters)
				s += param.Replace("out ", "[OutAttribute] ") + ", ";
			
			if (Parameters.Length > 0)
				s = s.Substring(0, s.Length - 2);
			
			s += ")\n\t\t{\n";
			
			string ultrapre = "";
			string core = "";
			string inner = "gl" + Name + "(§±)";
			string ultrapost = "";
			
			if (ReturnType != "void" && MustDoLateReturn)
			{
				ultrapre = ReturnType + " retVal;\n\t\t\t";
				ultrapost = "\n\t\t\treturn retVal;";
				
				inner = "retVal = " + ReturnConversionPattern.Replace("$", inner) + ";";
			}
			else
				inner = ((ReturnType != "void") ? "return " : "") + ReturnConversionPattern.Replace("$", inner) + ";";
			
			for (int i = 0; i < Parameters.Length; i++)
			{
				string[] paramBits = Parameters[i].Split(' ');
				string paramName = paramBits[paramBits.Length - 1];
				core += ParametersConversionPattern[i].Replace("$", paramName);
				inner = ParametersConversionPrefixes[i].Replace("$", paramName) + inner + ParametersConversionPostfixes[i].Replace("$", paramName);
				
				if (i < Parameters.Length - 1)
					core += ", ";
			}
			
			inner = inner.Replace("§±", core);
			inner = ultrapre + ReturnConversionPrefix + inner + ReturnConversionPostfix + ultrapost;
			
			s += "\t\t\t" + inner + "\n\t\t}\n";
			
			return s;
		}
	}
}
